package top.util.concurrent.utils;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

/**
 * @author He Kuntao
 * @since 2025/6/13 9:33
 */
public class FCountDownLatch {

    private final Sync sync;

    public FCountDownLatch(int count) {
        if (count < 0) {
            throw new IllegalArgumentException("count < 0");
        }
        this.sync = new Sync(count);
    }


    /**
     * 减少计数器，如果计数器达到0，则释放所有等待线程
     */
    public void countDown() {
        sync.releaseShared(1);
    }

    /**
     * 等待直到达到计数器 0
     *
     * @throws InterruptedException 中断异常
     */
    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

    /**
     * 等待直到达到计数器 0 或者 timeout
     *
     * @param timeout 超时时间
     * @param unit    时间单位
     * @return true 表示成功，false 表示超时
     * @throws InterruptedException 中断异常
     */
    public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

    /**
     * 获取当前计数
     *
     * @return 当前计数
     */
    public long getCount() {
        return sync.getCount();
    }

    /**
     * 静态内部类，实现同步逻辑
     */
    private static final class Sync extends AbstractQueuedSynchronizer {

        Sync(int count) {
            setState(count);
        }

        int getCount() {
            return getState();
        }

        @Override
        protected int tryAcquireShared(int arg) {
            return getState() == 0 ? 1 : -1;
        }

        @Override
        protected boolean tryReleaseShared(int arg) {
            for (; ; ) {
                int c = getState();
                if (c == 0) {
                    return false;
                }
                int nextc = c - 1;
                if (compareAndSetState(c, nextc)) {
                    return nextc == 0;
                }
            }
        }
    }
}
